//
//  QSBaseWebViewController.swift
//  TestSwift
//
//  Created by Song on 2018/7/3.
//  Copyright © 2018年 Song. All rights reserved.
//

import UIKit
import WebKit

class QSBaseWebViewController: QSBaseViewController, WKUIDelegate, WKNavigationDelegate {
    // 子控件
    var webView: WKWebView?
    var progressView: UIProgressView?
    
    // 标题位置
    var titleAlignment: NSTextAlignment = .left
    // webView的配置上下文
    var webContent: WKUserContentController!
    
    // 重新刷新
    var refreshAction: (() -> ())? {
        didSet {
            errorView.reloadBlock = refreshAction
        }
    }
    
    var webViewLoadSuccess: (() -> ())?
    var webViewLoadError: (() -> ())?
    
    // 属性
    var urlStr: String?
    
    override func qs_setupSubViews() {
        // 基本配置
        let config = WKWebViewConfiguration()
        // 创建UserContentController（提供JavaScript向webView发送消息的方法）
        webContent = WKUserContentController()
        // 将UserConttentController设置到配置文件
        config.userContentController = webContent
        
        // webView
        webView = WKWebView.init(frame: CGRect.zero, configuration: config)
        if #available(iOS 11.0, *) {
            webView?.scrollView.contentInsetAdjustmentBehavior = .never
        }
        self.view.addSubview(webView!)
        webView!.snp.makeConstraints { (make) in
            make.edges.equalTo(UIEdgeInsets.zero)
        }
        
        webView?.addObserver(self, forKeyPath: "estimatedProgress", options: NSKeyValueObservingOptions.new, context: nil)
        webView?.addObserver(self, forKeyPath: "title", options: NSKeyValueObservingOptions.new, context: nil)
        webView?.uiDelegate = self
        webView?.navigationDelegate = self
        
        // progressView
        progressView = UIProgressView.init()
        self.view.addSubview(progressView!)
        progressView?.snp.makeConstraints({ (make) in
            make.top.left.right.equalTo(0.0)
            make.height.equalTo(2.0)
        })
        
        progressView?.trackTintColor = .clear
        progressView?.isHidden = true
        
        // errorView
        self.view.addSubview(self.errorView)
        self.errorView.snp.makeConstraints { (make) in
            make.edges.equalTo(UIEdgeInsets.zero)
        }
        
        self.errorView.isHidden = true
    }
    
    /// 返回
    override func qs_back() {
        if (self.webView?.canGoBack)! {
            self.webView?.goBack()
        } else {
            if let nav = self.navigationController {
                nav.popViewController(animated: true)
            }
        }
    }
    
    // MARK: - Private Methods
    /// 加载网页
    ///
    /// - Parameter urlStr: 网页URl
    func qs_loadWithUrlStr(_ urlStr: String) {
        self.urlStr = urlStr
        
        let url = URL.init(string: urlStr.qs_urlEncoded())
        let request = URLRequest.init(url: url!, cachePolicy: URLRequest.CachePolicy.useProtocolCachePolicy, timeoutInterval: 20)
        self.webView?.load(request)
    }
    
    /// 进度条加载
    ///
    /// - Parameter timer: 定时器
    @objc private func progressAction(timer: Timer) {
        self.progressView?.progress += 0.01
        
        if (self.progressView?.progress)! >= Float(0.9) {
            timer.invalidate()
            
            self.progressView?.isHidden = true
            self.progressView?.progress = 0.0
        }
    }
    
    /// 添加JS调用方法名
    ///
    /// - Parameter methName: 方法名
    func qs_addJSMethodName(methName: String, action: ((Any) -> ())?) {
        let messHandler = QSWebJSMessageHandler.share
        if let block = action {
            messHandler.actionArr[methName] = block
        }
        self.webContent.add(messHandler, name: methName)
    }
    
    /// 删除JS调用方法名
    ///
    /// - Parameter methName: 方法名
    func qs_deleteJSMethodName(methName: String) {
        self.webContent.removeScriptMessageHandler(forName: methName)
        
        let messHandler = QSWebJSMessageHandler.share
        messHandler.actionArr.removeValue(forKey: methName)
    }
    
    /// 配置userAgent
    func qs_configUserAgent(_ userAgent: String) {
        UserDefaults.standard.register(defaults: ["UserAgent": userAgent])
    }
    
    // MARK: - WKNavigationDelegate
    /// 开始加载
    func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
        self.progressView?.isHidden = false
        self.errorView.isHidden = true
        
        self.progressView?.setProgress(0.05, animated: true)
    }
    
    /// 加载完成
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        if let block = webViewLoadSuccess {
            block()
        }
    }
    
    /// 网页在提交数据失败时调用
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        self.errorView.isHidden = false
        
        if let block = webViewLoadError {
            block()
        }
    }
    
    /// 加载错误
    func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
        self.errorView.isHidden = false
        
        if let block = webViewLoadError {
            block()
        }
    }
    
    /// 在发送请求前,决定是否跳转
    func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
        let url = navigationAction.request.url
        let scheme = url?.scheme
        
        var actionPolicy = WKNavigationActionPolicy.allow
        if url != nil {
            actionPolicy = QSWebJSMessageHandler.share.qs_redirectionUrl(url!, scheme: scheme ?? "")
        }
        
        /* 这句话一定要实现 不然会异常 */
        decisionHandler(actionPolicy);
    }
    
    func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // 允许加载未信任的网页
        let cred = URLCredential.init(trust: challenge.protectionSpace.serverTrust!)
        completionHandler(.useCredential, cred)
    }
    
    // MARK: - KVO
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if keyPath == "estimatedProgress" {
            let newprogress = change![NSKeyValueChangeKey.newKey] as! Double
            if (object as? WKWebView) != nil && (object as! WKWebView) == self.webView {
                if newprogress == 1.0 {
                    if #available(iOS 10.0, *) {
                        Timer.scheduledTimer(withTimeInterval: 0.01, repeats: true, block: { (timer) in
                            self.progressAction(timer: timer)
                        })
                    } else {
                        Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: #selector(self.progressAction(timer:)), userInfo: nil, repeats: true)
                    }
                }
            } else {
                self.progressView?.isHidden = false
                self.progressView?.setProgress(Float(newprogress > 0.25 ? newprogress : 0.25), animated: true)
            }
        } else if keyPath == "title" {
            // 设置导航栏标题
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) {
                if let title = self.webView?.title {
                    self.title = title
                }
            }
        }
    }
    
    // MARK: - Lazy
    lazy var errorView: QSWebErrorView = {
        let errorView = QSWebErrorView.init(with: {
            self.progressView?.progress = 0.0
            self.qs_loadWithUrlStr(self.urlStr!)
        })
        return errorView
    }()
    
    deinit {
        self.webView?.removeObserver(self, forKeyPath: "estimatedProgress")
        self.webView?.removeObserver(self, forKeyPath: "title")
    }
}
